Skip to main content

API Key External API (/api/ext)

App: Minotaur Sales API
Published by: Minotaur Sales
Supported on: app.minotaursales.io


Documentation for external endpoints protected with an API Key.

Authentication​

All endpoints in this document use:

Authorization: X-API-Key YOUR_API_KEY
Content-Type: application/json

Base URL:

https://api.minotaursales.io/api/ext

Example:

curl --location 'https://api.minotaursales.io/api/ext/contacts/list' \
--header 'Authorization: X-API-Key YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{}'

Common response formats​

DefaultResponse​

Many create/update/delete endpoints respond with:

{
"success": true,
"data": {},
"message": "Operation completed"
}

PaginateResponse<T>​

{
"data": [],
"pagination": {
"total_records": 0,
"current_page": 1,
"total_pages": 1
}
}

Customer (/customer)​

GET /customer/summary (customer:read)​

Returns the summary of the customer associated with the API key: account data, user count, and active subscription.

Response 200:

{
"customer": {
"id": "7a70f0db-aa4c-43fd-bbf5-f7b0d33c9172",
"business_name": "Acme Inc",
"status": "OK",
"country": null,
"city": null
},
"users_count": 5,
"subscription": {
"id": "3a35dea5-7354-43c8-a3ea-5abec718b2ab",
"status": "active",
"balance": 40000,
"price": "20000",
"periodicity": "month",
"currency": "usd",
"tier": {
"id": "66c609bc-cb1a-4a2b-a34b-212d3acb616b",
"title": "Free Tier",
"tier": 1,
"is_free": true,
"price": "20000"
},
"active_seats": 1
}
}

Contacts (/contacts)​

POST /contacts/list (contacts:read)​

Request (minimal example):

{
"filters": {},
"paginate": {
"page": 1,
"limit": 25
}
}

Response 200 (ContactsResponse[]):

[
{
"id": "7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c",
"first_name": "Ana",
"middle_name": null,
"last_name": "Perez",
"gender": null,
"birth_year": null,
"linkedin_url": null,
"facebook_url": null,
"twitter_url": null,
"work_email": "ana@example.com",
"personal_email": null,
"other_emails": null,
"industry": "Software",
"job_title": "Engineer",
"location_locality": "Bogota",
"location_country": "CO",
"location_region": "Cundinamarca",
"location_postal_code": null,
"phone_numbers": [],
"company": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"company_name": "Acme",
"industry": "Software"
},
"mobile_phone": null,
"score": 87,
"verification_status": "verified",
"last_verified": "2026-04-01T10:30:00.000Z",
"hubspot_synced_at": null,
"custom_fields": {}
}
]

POST /contacts/metadata (contacts:read)​

Request:

{
"filters": {},
"paginate": {
"page": 1,
"limit": 25
}
}

Response 200 (ContactMetadataResponse):

{
"pagination": {
"current_page": 1,
"total_records": 1,
"total_pages": 1
}
}

POST /contacts (contacts:create)​

Required fields:

  • first_name
  • last_name
  • work_email
  • phone_numbers (can be an empty array)

Optional fields:

  • assigned_to β€” UUID of the user to assign the contact to. If not specified, the contact remains unassigned.
  • list_ids β€” UUIDs of existing lists to add the contact to. The contact is only added to lists sent explicitly; the API key does not automatically create or use "My Contacts". Without list_ids, the contact is not added to any list.
  • company β€” object with id (existing company) or name (finds or creates by name). Both fields are optional; industry is optional when creating by name.

Request:

{
"first_name": "Ana",
"last_name": "Perez",
"work_email": "ana@example.com",
"phone_numbers": [],
"job_title": "Engineer",
"company": {
"name": "Acme",
"industry": "Software"
},
"list_ids": ["f1e2d3c4-b5a6-7890-abcd-ef1234567890"],
"assigned_to": "6cbe57bf-bf80-44c0-a2f7-8d6d4ca85dbd"
}

Response 201 (DefaultResponse):

{
"success": true,
"message": "Contact created successfully"
}

GET /contacts/:id (contacts:read)​

Response 200 (ContactsResponse):

{
"id": "7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c",
"first_name": "Ana",
"middle_name": null,
"last_name": "Perez",
"gender": null,
"birth_year": null,
"linkedin_url": null,
"facebook_url": null,
"twitter_url": null,
"work_email": "ana@example.com",
"personal_email": null,
"other_emails": null,
"industry": "Software",
"job_title": "Engineer",
"location_locality": "Bogota",
"location_country": "CO",
"location_region": "Cundinamarca",
"location_postal_code": null,
"phone_numbers": [],
"company": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"company_name": "Acme",
"industry": "Software"
},
"mobile_phone": null,
"score": 87,
"verification_status": "verified",
"last_verified": "2026-04-01T10:30:00.000Z",
"hubspot_synced_at": null,
"custom_fields": {}
}

PATCH /contacts/:id (contacts:update)​

All fields are optional; only fields sent in the body are updated.

Relevant fields:

  • assigned_to β€” UUID of the user to assign the contact to.
  • list_ids β€” UUIDs of existing lists to add the contact to. Only associates if sent explicitly; the API key does not use "My Contacts" automatically.
  • company β€” object with id (existing company) or name (finds or creates by name). industry is optional when creating by name.

Request:

{
"job_title": "Senior Engineer",
"phone_numbers": [
{ "country_code": "+57", "number": "3001234567" }
],
"company": {
"name": "Acme",
"industry": "Software"
},
"list_ids": ["f1e2d3c4-b5a6-7890-abcd-ef1234567890"],
"assigned_to": "6cbe57bf-bf80-44c0-a2f7-8d6d4ca85dbd"
}

Response 200 (DefaultResponse):

{
"success": true
}

DELETE /contacts/:id (contacts:delete)​

Response 200 (DefaultResponse):

{
"success": true,
"data": {},
"message": "Contact deleted"
}

Companies (/company)​

POST /company/list (companies:read)​

Request:

{
"filters": {},
"paginate": {
"page": 1,
"limit": 25
}
}

Response 200 (CompaniesResponse[]):

[
{
"id": "30ea8d4e-6b76-4f8f-bcf8-a1cc5af13b4b",
"company_name": "Acme Inc",
"size": "51-200",
"industry": "Software",
"twitter_url": null,
"linkedin_url": "https://linkedin.com/company/acme",
"facebook_url": null,
"location_locality": "Bogota",
"location_metro": null,
"location_region": "Cundinamarca",
"location_street_address": null,
"location_address_line_2": null,
"location_postal_code": null,
"location_country": "CO",
"last_verified": "2026-04-01T10:30:00.000Z",
"verification_status": "verified",
"score": 80,
"custom_fields": {}
}
]

POST /company/metadata (companies:read)​

Request:

{
"filters": {},
"paginate": {
"page": 1,
"limit": 25
}
}

Response 200 (CompanyMetadataResponse):

{
"pagination": {
"current_page": 1,
"total_records": 1,
"total_pages": 1
}
}

POST /company (companies:create)​

Required fields:

  • type
  • company_name

Request:

{
"type": "COMPANY",
"company_name": "Acme Inc",
"industry": "Software"
}

Response 201 (DefaultResponse):

{
"success": true,
"message": "Company created successfully"
}

GET /company/:id (companies:read)​

Response 200 (CompaniesResponse | null)

PATCH /company/:id (companies:update)​

Request:

{
"industry": "SaaS",
"location_country": "CO"
}

Response 200 (DefaultResponse)

DELETE /company/:id (companies:delete)​

Response 200 (DefaultResponse)


Lists (/list-contact)​

POST /list-contact/list (list_contacts:read)​

Request (page and limit at the body root):

{
"page": 1,
"limit": 25
}

Response 200 (ListContactResponse[]):

[
{
"id": "9f720ce2-f5d1-4ef4-a0c8-3399f68d386d",
"name": "Prospects Latam",
"description": "Initial list",
"owner_id": "6cbe57bf-bf80-44c0-a2f7-8d6d4ca85dbd",
"owner_name": "API Owner",
"source": "manual",
"collaborators": [],
"rules": [
{
"field": "location_country",
"operator": "contains",
"value": "CO",
"logic_operator": "AND"
}
],
"contacts_count": 120,
"created_at": "2026-04-01T10:30:00.000Z",
"updated_at": "2026-04-01T10:30:00.000Z"
}
]

POST /list-contact (list_contacts:create)​

Request:

{
"name": "Prospects Latam",
"description": "Initial list",
"rules": [
{
"field": "location_country",
"operator": "contains",
"value": "CO"
}
]
}

Response 201 (CreateListContactResponse):

{
"id": "9f720ce2-f5d1-4ef4-a0c8-3399f68d386d",
"name": "Prospects Latam"
}

PATCH /list-contact/:id (list_contacts:update)​

Request:

{
"name": "Prospects Latam v2",
"description": "Updated list"
}

Response 200 (DefaultResponse)

DELETE /list-contact/:id (list_contacts:delete)​

Response 200 (DefaultResponse)

POST /list-contact/duplicate (list_contacts:read)​

Request:

{
"list_id": "9f720ce2-f5d1-4ef4-a0c8-3399f68d386d",
"new_name": "Prospects Latam Copy"
}

Response 200 (DefaultResponse)

POST /list-contact/verify-contacts/:id (list_contacts:read)​

No body. Starts the verification process for the contacts in the list.

Response 200 (DefaultResponse)


List Contact Details (/list-contact-details)​

POST /list-contact-details/add-contacts (list_contact_details:update)​

Adds one or more existing contacts to a list.

Request:

{
"list_id": "9f720ce2-f5d1-4ef4-a0c8-3399f68d386d",
"contact_ids": [
"7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c",
"a96f2d7f-743f-4747-9198-7ca35ccab774"
]
}

Response 200 (DefaultResponse):

{
"success": true,
"message": "Contacts added successfully"
}

Products (/products)​

POST /products/list (products:read)​

Request:

{
"paginate": {
"page": 1,
"limit": 25
}
}

Response 201 (ProductListItemResponse[]):

[
{
"id": "f3c1b2a0-9d4e-4b8a-a2e1-1c3d5e7f9b0c",
"name": "Basic Plan",
"currency": "USD",
"price": 99.99,
"unit": "month",
"active": true,
"opportunities_count": 3,
"pipelines_count": 1,
"created_at": "2026-04-01T10:30:00.000Z",
"updated_at": "2026-04-01T10:30:00.000Z"
}
]

POST /products (products:create)​

Required fields:

  • name
  • price
  • unit

Request:

{
"name": "Basic Plan",
"price": 99.99,
"unit": "month",
"currency": "USD"
}

Response 201 (DefaultResponse):

{
"success": true,
"message": "Product created successfully"
}

GET /products/:id (products:read)​

Response 200 (ProductResponse):

{
"id": "f3c1b2a0-9d4e-4b8a-a2e1-1c3d5e7f9b0c",
"name": "Basic Plan",
"currency": "USD",
"price": 99.99,
"unit": "month",
"active": true,
"created_at": "2026-04-01T10:30:00.000Z",
"updated_at": "2026-04-01T10:30:00.000Z"
}

PATCH /products/:id (products:update)​

Request:

{
"name": "Basic Plan v2",
"price": 119.99
}

Response 200 (DefaultResponse)

DELETE /products/:id (products:delete)​

Response 200 (DefaultResponse)


Opportunities (/opportunities)​

POST /opportunities/list (opportunities:read)​

Request:

{
"paginate": {
"page": 1,
"limit": 25
}
}

Response 201 (OpportunityResponse[]):

[
{
"id": "e2d4f6a8-1b3c-5d7e-9f0a-2b4c6d8e0f1a",
"name": "Deal with Acme",
"description": "Initial opportunity",
"price": 500.00,
"priority": "HIGHT",
"stage_id": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
"contacts_ids": ["7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c"],
"company_id": "30ea8d4e-6b76-4f8f-bcf8-a1cc5af13b4b",
"user_id_assigned": "6cbe57bf-bf80-44c0-a2f7-8d6d4ca85dbd",
"estimated_closing_date": "2026-07-01T00:00:00.000Z",
"close_date": "2026-07-15T00:00:00.000Z",
"details": []
}
]

POST /opportunities (opportunities:create)​

Creates an opportunity and associates it with contacts, company, products, and an assigned user.

Required fields:

  • name
  • contacts_ids β€” array of existing contact UUIDs
  • stage_id β€” UUID of the pipeline stage
  • user_id_assigned β€” UUID of the responsible user
  • products β€” array of products (can be [])
  • estimated_closing_date β€” estimated closing date (ISO 8601)
  • close_date β€” closing date (ISO 8601)
  • priority β€” URGENT | HIGHT | MEDIUM | LOW | NONE

Optional fields:

  • description
  • company_id β€” UUID of the related company
  • source_id β€” UUID of the source

Request:

{
"name": "Deal with Acme",
"description": "Initial opportunity",
"contacts_ids": ["7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c"],
"company_id": "30ea8d4e-6b76-4f8f-bcf8-a1cc5af13b4b",
"stage_id": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
"user_id_assigned": "6cbe57bf-bf80-44c0-a2f7-8d6d4ca85dbd",
"estimated_closing_date": "2026-07-01T00:00:00.000Z",
"close_date": "2026-07-15T00:00:00.000Z",
"priority": "HIGHT",
"products": [
{
"id": "f3c1b2a0-9d4e-4b8a-a2e1-1c3d5e7f9b0c",
"price": 99.99,
"quantity": 2
}
]
}

Response 201 (DefaultResponse):

{
"success": true,
"message": "Opportunity created successfully"
}

GET /opportunities/:id (opportunities:read)​

Response 200 (OpportunityResponse)

PATCH /opportunities/:id (opportunities:update)​

All fields are optional. To update products use the products.add, products.remove, products.update structure.

Request:

{
"name": "Deal with Acme - Updated",
"priority": "URGENT",
"products": {
"add": [
{ "id": "f3c1b2a0-9d4e-4b8a-a2e1-1c3d5e7f9b0c", "price": 99.99, "quantity": 1 }
],
"remove": ["a0b1c2d3-e4f5-6789-abcd-ef0123456789"],
"update": [
{ "id": "f3c1b2a0-9d4e-4b8a-a2e1-1c3d5e7f9b0c", "quantity": 3 }
]
}
}

Response 200 (DefaultResponse)

DELETE /opportunities/:id (opportunities:delete)​

Response 200 (DefaultResponse)


Pipelines (/pipelines)​

GET /pipelines (pipelines:read)​

Returns all pipelines for the customer.

Response 200 (PipelineExternalItem[]):

[
{
"id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"name": "Sales Pipeline",
"description": "Main pipeline",
"currency": "USD",
"active": true
}
]

GET /pipelines/:id (pipelines:read)​

Returns the pipeline with its stages.

Response 200 (PipelineResponse):

{
"id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"name": "Sales Pipeline",
"description": "Main pipeline",
"currency": "USD",
"active": true,
"visibility": "PUBLIC",
"stages": [
{
"id": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
"name": "Prospect",
"order": 1,
"pipeline_id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"probability_percentage": 10,
"status": "OPEN"
}
],
"created_at": "2026-04-01T10:30:00.000Z",
"updated_at": "2026-04-01T10:30:00.000Z"
}

Stages (/stages)​

POST /stages/list (stages:read)​

Returns the stages of a pipeline.

Required fields:

  • pipeline_id β€” UUID of the pipeline

Request:

{
"pipeline_id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"paginate": {
"page": 1,
"limit": 25
}
}

Response 201 (StageResponse[]):

[
{
"id": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
"name": "Prospect",
"order": 1,
"pipeline_id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f",
"probability_percentage": 10,
"status": "OPEN",
"total_opportunities": 5
}
]

Prospect (/prospect)​

Requires connectivity to the Elasticsearch cluster.

POST /prospect/filters (prospect:read)​

Returns suggested values for filter autocomplete.

Request (FiltersDto):

{
"source": "job_title",
"search": "engineer"
}

Response 201 (list of suggested values):

[
{
"type": "job_title",
"value": "Software Engineer"
}
]

POST /prospect/metadata (prospect:read)​

paginate.limit accepts only: 10, 25, 50, 100.

Request (GetBatchContactsDto):

{
"filters": {},
"paginate": {
"page": 1,
"limit": 25
},
"all_contacts": false
}

Response 201 (MetadataContactFilterResponse):

{
"pagination": {
"current_page": 1,
"total_records": 1200,
"total_pages": 48
},
"filters_applied": {
"first_name": [],
"last_name": [],
"job_title": [],
"job_company_name": [],
"job_company_industry": [],
"location_locality": [],
"location_region": [],
"location_country": [],
"location_postal_code": [],
"date_verified": {
"gte": null,
"lte": null
}
}
}

POST /prospect/list (prospect:read)​

paginate.limit accepts only: 10, 25, 50, 100.

Request (GetBatchContactsDto):

{
"filters": {},
"paginate": {
"page": 1,
"limit": 25
},
"all_contacts": false
}

Response 201 (ProspectContactResponse[]):

[
{
"_id": "6638f0f0507f4b2cb54f4f3e",
"first_name": "Ana",
"last_name": "Perez",
"job_title": "Engineer",
"job_company_name": "Acme",
"job_company_industry": "Software",
"work_email": "ana@example.com",
"emails": ["ana@example.com"],
"mobile_phone": null,
"location_locality": "Bogota",
"location_region": "Cundinamarca",
"location_country": "CO",
"location_postal_code": null,
"facebook_url": null,
"linkedin_url": null,
"twitter_url": null,
"verification_status": "verified",
"score": 82,
"date_verified": "2026-04-01T10:30:00.000Z"
}
]

Service Handler (/service-handler)​

POST /service-handler/unlock-contacts (payment_prospect:create)​

Unlocks contacts from the prospect catalog based on filters. Consumes subscription credits.

Request (UnlockContactsDto):

{
"filters": {},
"order_by": {
"score": "DESC"
},
"total_records": 100,
"sync_hubspot": false
}

Response 200 (ServiceHandlerResponse):

{
"id": "7ec0d9c6-cab6-46cf-8d5a-b5f22f17f6da",
"status": "PENDING"
}

POST /service-handler/unlock-selected-contacts (payment_prospect:create)​

Unlocks specific contacts by ID. Consumes subscription credits.

Request (UnlockSelectedContactsDto):

{
"ids": [
"7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c",
"a96f2d7f-743f-4747-9198-7ca35ccab774"
],
"sync_hubspot": false
}

Response 200 (ServiceHandlerResponse):

{
"id": "dc7248f7-bc52-4710-b854-a8caac8ca5a6",
"status": "PENDING"
}

POST /service-handler/verify-email (verify_email:create)​

Starts the email verification process for a list of contacts. Consumes verification credits.

Request (VerifyEmailDto):

{
"emails": [
{
"email": "ana@example.com",
"contact_id": "7b9c3df7-0eb5-4be2-af74-7e48d4b43b9c"
}
],
"sync_hubspot": false
}

Response 200 (ServiceHandlerResponse):

{
"id": "f2c4f038-63fc-4f78-a86d-88f26a7398d8",
"status": "PENDING"
}

Common errors​

401 Unauthorized​

When the Authorization header is missing or invalid:

{
"statusCode": 401,
"message": "The provided API key is invalid or unauthorized."
}

400 Bad Request​

When the request body fails validation (required fields, invalid UUID, incorrect types, limit out of range).

403 Forbidden​

When the API key does not have the required permission for the endpoint:

{
"statusCode": 403,
"message": "User does not have permission"
}